﻿
using cpe.cpein.UI.UserCpeInServiceReference;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace cpe.cpein.UI.Controls
{
    /// <summary>
    /// Interaction logic for UCGroup.xaml
    /// </summary>
    public partial class UCGroup : UserControl
    {
        #region Variables declaration

        /// <summary>
        /// Connection to WebService Group
        /// </summary>
        UsersServiceClient userService = new UsersServiceClient();

        /// <summary>
        /// Current Group.
        /// </summary>
        Group _currentGroup;

        /// <summary>
        /// Current user.
        /// </summary>
        User _currentUser;

        /// <summary>
        /// Parent of the User Control.
        /// </summary>
        FMainWindow _fParent;

        /// <summary>
        /// Group Members
        /// </summary>
        private List<User> _groupMembers = new List<User>();
        public List<User> MyGroupMembers
        {
            get { return _groupMembers; }
            set { _groupMembers = value; }
        }

        /// <summary>
        /// Group Types
        /// </summary>
        private List<GroupType> _groupTypes = new List<GroupType>();
        public List<GroupType> MyGroupTypes
        {
            get { return _groupTypes; }
            set { _groupTypes = value; }
        }

        /// <summary>
        /// Countries
        /// </summary>
        private List<Country> _countries = new List<Country>();
        public List<Country> MyCountries
        {
            get { return _countries; }
            set { _countries = value; }
        }

        /// <summary>
        /// Contains the group's Address
        /// </summary>
        private Address _groupAddress;

        /// <summary>
        /// Allows to know if the UC is in Editable mode.
        /// </summary>
        bool isEditMode = false;

        #endregion

        #region Create and Open

        /// <summary>
        /// Default constructor.
        /// </summary>
        public UCGroup()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Constructor with parameters.
        /// </summary>
        /// <param name="p"></param>
        public UCGroup(User u, Group p, FMainWindow pf)
        {
            InitializeComponent();
            this._currentGroup = p;
            this._currentUser = u;
            this._fParent = pf;
        }

        /// <summary>
        /// Function used to to initialize the current UserControl.
        /// </summary>
        private void InitializeUC()
        {
            FillForm();
        }

        /// <summary>
        /// Function fires when control is Loaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeUC();
            SetReadMode();
        }

        #endregion

        #region Events methods

        /// <summary>
        /// Function fires when button Edit is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btEdit_Click(object sender, RoutedEventArgs e)
        {
            SetEditableMode();
        }

        /// <summary>
        /// Function fires when button Refresh is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btRefresh_Click(object sender, RoutedEventArgs e)
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                Group grp = us.GetGroupByID(this._currentGroup.Id, this._currentUser);
                this._fParent.LoadUserControl(new UCGroup(this._currentUser, grp, this._fParent));
            }
        }

        /// <summary>
        /// Function fires when button Validate is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btValidate_Click(object sender, RoutedEventArgs e)
        {
            SaveChanges();
            SetReadMode();
        }

        /// <summary>
        /// Function fires when button Refresh is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btCancel_Click(object sender, RoutedEventArgs e)
        {
            RefreshObject();
            SetReadMode();
        }

        /// <summary>
        /// Function fires when button Connect is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btConnect_Click(object sender, RoutedEventArgs e)
        {
            ConnectGroup();
        }

        /// <summary>
        /// Function fires when button Disconnect is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btDisconnect_Click(object sender, RoutedEventArgs e)
        {
            DisconnectGroup();
        }

        /// <summary>
        /// Function fires when a member is double clicked into the grid.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MembersGrid_DblClick(object sender, MouseButtonEventArgs e)
        {
            if (MembersGrid.SelectedValue != null)
            {
                using (UsersServiceClient us = new UsersServiceClient())
                {
                    int usId = int.Parse(MembersGrid.SelectedValue.ToString());
                    this._fParent.LoadUserControl(new UCUser(us.GetUserByID(usId, this._currentUser), this._currentUser));
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Function used to disconnect the current user from the current group.
        /// </summary>
        private void DisconnectGroup()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                bool res = us.DisconnectUserToGroup(this._currentGroup, this._currentUser, this._currentUser);
            }
            btRefresh_Click(this, new RoutedEventArgs());
        }

        /// <summary>
        /// Function used to connect the current user with the current group.
        /// </summary>
        private void ConnectGroup()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                bool res = us.ConnectUserToGroup(this._currentGroup, this._currentUser, this._currentUser); 
            }
            btRefresh_Click(this, new RoutedEventArgs());
        }

        /// <summary>
        /// Function used to save changes on the group.
        /// </summary>
        private void SaveChanges()
        {
            SetValuesFromFields();
            using (UsersServiceClient us = new UsersServiceClient())
            {
                us.UpdateGroup(this._currentGroup, this._currentUser);
            }
            btRefresh_Click(this, new RoutedEventArgs());
        }

        /// <summary>
        /// Function which allows to set the current edit object with the fields values.
        /// </summary>
        private void SetValuesFromFields()
        {
            this._currentGroup.Description = txtCompanyDescription.Text;
            this._currentGroup.IDType = (cmbType.SelectedValue != null) ? int.Parse(cmbType.SelectedValue.ToString()) : 0;
            this._currentGroup.Label = txtCompanyName.Text;
        }

        /// <summary>
        /// Function used to refresh the current group.
        /// </summary>
        private void RefreshObject()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                this._currentGroup = us.GetGroupByID(this._currentGroup.Id, this._currentUser);
            }
            InitializeUC();
        }

        /// <summary>
        /// Function which handle the buttons states.
        /// </summary>
        private void InitializeActions()
        {
            bool isConnected = IsConnectUser();

            if (isEditMode)
            {
                this.btEdit.Visibility = System.Windows.Visibility.Hidden;
                this.btRefresh.Visibility = System.Windows.Visibility.Hidden;
                this.btValidate.Visibility = System.Windows.Visibility.Visible;
                this.btCancel.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                this.btEdit.Visibility = System.Windows.Visibility.Visible;
                this.btRefresh.Visibility = System.Windows.Visibility.Visible;
                this.btValidate.Visibility = System.Windows.Visibility.Hidden;
                this.btCancel.Visibility = System.Windows.Visibility.Hidden;
            }

            // User is connected to the group
            if (isConnected)
            {
                this.btConnect.Visibility = System.Windows.Visibility.Hidden;
                this.btDisconnect.Visibility = System.Windows.Visibility.Visible;
                this.btEdit.Visibility = System.Windows.Visibility.Visible;
            }
            // User is not connected to the group
            else
            {
                this.btConnect.Visibility = System.Windows.Visibility.Visible;
                this.btDisconnect.Visibility = System.Windows.Visibility.Hidden;
                this.btEdit.Visibility = System.Windows.Visibility.Hidden;
            }
        }

        /// <summary>
        /// Function which allows to know if the current user is connected to the group.
        /// </summary>
        /// <returns></returns>
        private bool IsConnectUser()
        {
            var req = from User in this.MyGroupMembers
                      where User.Id == this._currentUser.Id
                      select User;
            return (req.ToList().Count() > 0);
        }

        /// <summary>
        /// Function which allows to initialize the Lists.
        /// </summary>
        private void InitializeLists()
        {
            Tools.Tools.BeginWaitStatus();
            List<GroupType> grt = GetGroupTypes();
                List<Country> cty = GetCountries();
                List<User> usrs = GetGroupMembers();

                    this.MyGroupTypes.Clear();
                    this.MyGroupTypes.AddRange(grt);
                    this.cmbType.ItemsSource = this.MyGroupTypes;

                    this.MyCountries.Clear();
                    this.MyCountries.AddRange(cty);
                    this.cmbAddressCountry.ItemsSource = this.MyCountries;

                    this.MyGroupMembers.Clear();
                    this.MyGroupMembers.AddRange(usrs);
                    this.MembersGrid.ItemsSource = this.MyGroupMembers;

                    Tools.Tools.EndWaitStatus();
        }

        /// <summary>
        /// Function used to get the group types.
        /// </summary>
        private List<GroupType> GetGroupTypes()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                return new List<GroupType>(us.GetAllGroupTypes(this._currentUser));
            }
        }

        /// <summary>
        /// Function used to get the countries.
        /// </summary>
        private List<Country> GetCountries()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                return new List<Country>(us.GetAllCountries(this._currentUser));
            }
        }

        /// <summary>
        /// Function used to get the members of the group.
        /// </summary>
        /// <returns></returns>
        private List<User> GetGroupMembers()
        {
            using (UsersServiceClient us = new UsersServiceClient())
            {
                return new List<User>(us.GetGroupMembers(this._currentGroup, this._currentUser));
            }
        }

        /// <summary>
        /// Allow to fill all fields of the User Control with the current object.
        /// </summary>
        private void FillForm()
        {
            EmptyForm();
            if (this._currentGroup != null)
            {
                InitializeLists();
                this.lblTitleCompanyName.Text = this._currentGroup.Label;
                this.txtCompanyName.Text = this._currentGroup.Label;
                this.cmbType.SelectedValue = this._currentGroup.IDType;
                this.txtCompanyDescription.Text = this._currentGroup.Description;
            }
        }

        /// <summary>
        /// Function used to empty fields of the User Control
        /// </summary>
        private void EmptyForm()
        {
            this.lblTitleCompanyName.Text = "";
            this.txtCompanyName.Text = "";
            this.txtCompanyDescription.Text = "";
            this.cmbType.SelectedValue = null;
            this.txtAddressAddr.Text = "";
            this.txtAddressCity.Text = "";
            this.txtAddressLabel.Text = "";
            this.cmbAddressCountry.SelectedValue = null;
        }

        /// <summary>
        /// Allow to set editable or notall fields of the control.
        /// </summary>
        /// <param name="isEditable"></param>
        private void SetEditable(bool isEditable)
        {
            this.txtCompanyName.IsReadOnly = !isEditable;
            this.txtCompanyDescription.IsReadOnly = !isEditable;
            this.cmbType.IsReadOnly = !isEditable;
            this.txtAddressAddr.IsReadOnly = !isEditable;
            this.txtAddressCity.IsReadOnly = !isEditable;
            this.txtAddressLabel.IsReadOnly = !isEditable;
            this.cmbAddressCountry.IsReadOnly = !isEditable;
        }

        /// <summary>
        /// Function which allows to set the YC in Read mode.
        /// </summary>
        private void SetReadMode()
        {
            isEditMode = false;
            SetEditable(isEditMode);
            InitializeActions();
        }

        /// <summary>
        /// Function which allows to set the YC in Read mode.
        /// </summary>
        private void SetEditableMode()
        {
            isEditMode = true;
            SetEditable(isEditMode);
            InitializeActions();
        }

        #endregion

    }
}
